/*
 * @Author: yanjikun
 * @Date: 2022-01-05 17:22:46
 * @LastEditors: yanjikun
 * @LastEditTime: 2022-05-18 17:33:02
 * @Description: file content
 */
import { BasicHelpProps } from '@/components/BasicHelp'
import { Rule } from 'ant-design-vue/lib/form'
import { NamePath } from 'ant-design-vue/lib/form/interface'
import { Component, VNode } from 'vue'
import { ColEx, ComponentProps, ComponentType } from '.'
import { BasicFormType } from '../hooks'
import { FormItemProps } from './formItem'
/** 获取所有字段名 */
export type GetFieldKeys<T> = Exclude<keyof T, symbol | number>
export interface RenderCallbackParams<T = string> {
  config: FormConfig<T>
  formModel: T extends string ? Recordable : Record<GetFieldKeys<T>, any>
  field: T extends string ? string : GetFieldKeys<T>
  values: any
  /** 动态表单实例 */
  formInstance: BasicFormType
  /** 作用域插槽数据 */
  slotData?: Recordable
}
export interface FormConfig<T = any> {
  /**表单项字段名 */
  field: T extends string ? string : GetFieldKeys<T>
  /**表单项label */
  label: string
  /** 表单项对应的组件，eg: Input */
  component?: ComponentType | CustomRenderFn<T> | ((opt: RenderCallbackParams<T>) => Component)
  /** 表单组件slots，例如 a-input 的 suffix slot 可以写成：{ suffix: () => VNode } */
  componentSlots?:
    | ((renderCallbackParams: RenderCallbackParams<T>) => Recordable<CustomRenderFn<T>>)
    | Recordable<CustomRenderFn<T>>
    | ReturnType<CustomRenderFn>
  /**验证错误提示信息 */
  message?: string
  /**组件Props */
  componentProps?: ComponentProps | ((opt: RenderCallbackParams<T>) => ComponentProps)
  helpMessage?:
    | string
    | string[]
    | ((renderCallbackParams: RenderCallbackParams<T>) => string | string[])
  // BaseHelp component props
  helpComponentProps?: Partial<BasicHelpProps>
  /**是否必填 */
  required?: boolean
  /**验证规则 */
  rules?: Rule[]
  /**是否隐藏 */
  hidden?: boolean | ((renderCallbackParams: RenderCallbackParams<T>) => boolean)
  /**默认值 */
  defaultValue?: any
  /**label宽度 */
  labelWidth?: string | number
  /**组件col配置 */
  colProps?: Partial<ColEx>
  /**表单项Props */
  formItemProps?: Partial<FormItemProps>
  /**表单项插槽 */
  slot?: string

  /**动态设置表单项是否禁用 */
  dynamicDisabled?: boolean | ((renderCallbackParams: RenderCallbackParams<T>) => boolean)
}

export interface FormActionType {
  /**验证表单字段 */
  validateFields: (nameList?: NamePath[]) => Promise<any>
  validate: (nameList?: NamePath[]) => Promise<any>
  /**重置表单 */
  resetFields: () => void
  /**清除表单校验 */
  clearValidate: (name: string | string[]) => Promise<any>
  /**表单提交 */
  handleSubmit: (e?: Event | undefined) => Promise<Recordable<any> | undefined>
  /**设置表单值 */
  setFieldsValue: (values?: Recordable) => Promise<void>
  /**更新表单配置 */
  updateConfig: <T = any>(data: Partial<FormConfig<T>> | Partial<FormConfig<T>>[]) => Promise<void>
}
/** 自定义VNode渲染器 */
export type CustomRenderFn<T = any> = (
  renderCallbackParams: RenderCallbackParams<T>,
) => VNode | VNode[] | string
export type FormEmitType = {
  (event: 'register', ele: FormActionType): void
  (event: 'reset', data?: any): void
  (event: 'submit', data?: any): void
}
export type registerFun = (formEle: FormActionType) => void
export type useFormReturnType = [registerFun, FormActionType]

export type FieldMapToTime = [string, [string, string], string?][]
